home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 313_01 / fileio.c < prev    next >
C/C++ Source or Header  |  1990-04-21  |  6KB  |  270 lines

  1. /* $Header: /nw2/tony/src/stevie/src/RCS/fileio.c,v 1.12 89/08/06 09:50:01 tony Exp $
  2.  *
  3.  * Basic file I/O routines.
  4.  */
  5.  
  6. #include "stevie.h"
  7.  
  8. void
  9. filemess(s)
  10. char    *s;
  11. {
  12.     smsg("\"%s\" %s", (Filename == NULL) ? "" : Filename, s);
  13.     flushbuf();
  14. }
  15.  
  16. void
  17. renum()
  18. {
  19.     LPTR    *p;
  20.     unsigned long l = 0;
  21.  
  22.     for (p = Filemem; p != NULL ;p = nextline(p), l += LINEINC)
  23.         p->linep->num = l;
  24.  
  25.     Fileend->linep->num = 0xffffffff;
  26. }
  27.  
  28. #define    MAXLINE    256    /* maximum size of a line */
  29.  
  30. bool_t
  31. readfile(fname,fromp,nochangename)
  32. char    *fname;
  33. LPTR    *fromp;
  34. bool_t    nochangename;    /* if TRUE, don't change the Filename */
  35. {
  36.     FILE    *f, *fopen();
  37.     register LINE    *curr;
  38.     char    buff[MAXLINE], buf2[80];
  39.     register int    i, c;
  40.     register long    nchars = 0;
  41.     int    linecnt = 0;
  42.     bool_t    wasempty = bufempty();
  43.     int    nonascii = 0;        /* count garbage characters */
  44.     int    nulls = 0;        /* count nulls */
  45.     bool_t    incomplete = FALSE;    /* was the last line incomplete? */
  46.     bool_t    toolong = FALSE;    /* a line was too long */
  47.  
  48.     curr = fromp->linep;
  49.  
  50.     if ( ! nochangename )
  51.         Filename = strsave(fname);
  52.  
  53.     if ( (f=fopen(fixname(fname),"r")) == NULL )
  54.         return TRUE;
  55.  
  56.     filemess("");
  57.  
  58.     i = 0;
  59.     do {
  60.         c = getc(f);
  61.  
  62.         if (c == EOF) {
  63.             if (i == 0)    /* normal loop termination */
  64.                 break;
  65.  
  66.             /*
  67.              * If we get EOF in the middle of a line, note the
  68.              * fact and complete the line ourselves.
  69.              */
  70.             incomplete = TRUE;
  71.             c = NL;
  72.         }
  73.  
  74.         /*
  75.          * Abort if we get an interrupt, but finished reading the
  76.          * current line first.
  77.          */
  78.         if (got_int && i == 0)
  79.             break;
  80.  
  81.         if (c >= 0x80) {
  82.             c -= 0x80;
  83.             nonascii++;
  84.         }
  85.  
  86.         /*
  87.          * If we reached the end of the line, OR we ran out of
  88.          * space for it, then process the complete line.
  89.          */
  90.         if (c == NL || i == (MAXLINE-1)) {
  91.             LINE    *lp;
  92.  
  93.             if (c != NL)
  94.                 toolong = TRUE;
  95.  
  96.             buff[i] = '\0';
  97.             if ((lp = newline(strlen(buff))) == NULL)
  98.                 exit(1);
  99.  
  100.             strcpy(lp->s, buff);
  101.  
  102.             curr->next->prev = lp;    /* new line to next one */
  103.             lp->next = curr->next;
  104.  
  105.             curr->next = lp;    /* new line to prior one */
  106.             lp->prev = curr;
  107.  
  108.             curr = lp;        /* new line becomes current */
  109.             i = 0;
  110.             linecnt++;
  111.  
  112.         } else if (c == NUL)
  113.             nulls++;        /* count and ignore nulls */
  114.         else {
  115.             buff[i++] = c;        /* normal character */
  116.         }
  117.  
  118.         nchars++;
  119.  
  120.     } while (!incomplete && !toolong);
  121.  
  122.     fclose(f);
  123.  
  124.     /*
  125.      * If the buffer was empty when we started, we have to go back
  126.      * and remove the "dummy" line at Filemem and patch up the ptrs.
  127.      */
  128.     if (wasempty && nchars != 0) {
  129.         LINE    *dummy = Filemem->linep;    /* dummy line ptr */
  130.  
  131.         free(dummy->s);                /* free string space */
  132.         Filemem->linep = Filemem->linep->next;
  133.         free((char *)dummy);            /* free LINE struct */
  134.         Filemem->linep->prev = Filetop->linep;
  135.         Filetop->linep->next = Filemem->linep;
  136.  
  137.         Curschar->linep = Filemem->linep;
  138.         Topchar->linep  = Filemem->linep;
  139.     }
  140.  
  141.     renum();
  142.  
  143.     if (got_int) {
  144.         smsg("\"%s\" Interrupt", fname);
  145.         got_int = FALSE;
  146.         return FALSE;        /* an interrupt isn't really an error */
  147.     }
  148.  
  149.     if (toolong) {
  150.         smsg("\"%s\" Line too long", fname);
  151.         return FALSE;
  152.     }
  153.  
  154.     sprintf(buff, "\"%s\" %s%d line%s, %ld character%s",
  155.         fname,
  156.         incomplete ? "[Incomplete last line] " : "",
  157.         linecnt, (linecnt != 1) ? "s" : "",
  158.         nchars, (nchars != 1) ? "s" : "");
  159.  
  160.     buf2[0] = NUL;
  161.  
  162.     if (nonascii || nulls) {
  163.         if (nonascii) {
  164.             if (nulls)
  165.                 sprintf(buf2, " (%d null, %d non-ASCII)",
  166.                     nulls, nonascii);
  167.             else
  168.                 sprintf(buf2, " (%d non-ASCII)", nonascii);
  169.         } else
  170.             sprintf(buf2, " (%d null)", nulls);
  171.     }
  172.     strcat(buff, buf2);
  173.     msg(buff);
  174.  
  175.     return FALSE;
  176. }
  177.  
  178.  
  179. /*
  180.  * writeit - write to file 'fname' lines 'start' through 'end'
  181.  *
  182.  * If either 'start' or 'end' contain null line pointers, the default
  183.  * is to use the start or end of the file respectively.
  184.  */
  185. bool_t
  186. writeit(fname, start, end)
  187. char    *fname;
  188. LPTR    *start, *end;
  189. {
  190.     FILE    *f, *fopen();
  191.     FILE    *fopenb();        /* open in binary mode, where needed */
  192.     char    *backup;
  193.     register char    *s;
  194.     register long    nchars;
  195.     register int    lines;
  196.     register LPTR    *p;
  197.  
  198.     smsg("\"%s\"", fname);
  199.  
  200.     /*
  201.      * Form the backup file name - change foo.* to foo.bak
  202.      */
  203.     backup = alloc((unsigned) (strlen(fname) + 5));
  204.     strcpy(backup, fname);
  205.     for (s = backup; *s && *s != '.' ;s++)
  206.         ;
  207.     *s = NUL;
  208.     strcat(backup, ".bak");
  209.  
  210.     /*
  211.      * Delete any existing backup and move the current version
  212.      * to the backup. For safety, we don't remove the backup
  213.      * until the write has finished successfully. And if the
  214.      * 'backup' option is set, leave it around.
  215.      */
  216.     rename(fname, backup);
  217.  
  218.  
  219.     f = P(P_CR) ? fopen(fixname(fname), "w") : fopenb(fixname(fname), "w");
  220.  
  221.     if (f == NULL) {
  222.         emsg("Can't open file for writing!");
  223.         free(backup);
  224.         return FALSE;
  225.     }
  226.  
  227.     /*
  228.      * If we were given a bound, start there. Otherwise just
  229.      * start at the beginning of the file.
  230.      */
  231.     if (start == NULL || start->linep == NULL)
  232.         p = Filemem;
  233.     else
  234.         p = start;
  235.  
  236.     lines = nchars = 0;
  237.     do {
  238.         fprintf(f, "%s\n", p->linep->s);
  239.         nchars += strlen(p->linep->s) + 1;
  240.         lines++;
  241.  
  242.         /*
  243.          * If we were given an upper bound, and we just did that
  244.          * line, then bag it now.
  245.          */
  246.         if (end != NULL && end->linep != NULL) {
  247.             if (end->linep == p->linep)
  248.                 break;
  249.         }
  250.  
  251.     } while ((p = nextline(p)) != NULL);
  252.  
  253.     fclose(f);
  254.     smsg("\"%s\" %d line%s, %ld character%s", fname,
  255.         lines, (lines > 1) ? "s" : "",
  256.         nchars, (nchars > 1) ? "s" : "");
  257.  
  258.     UNCHANGED;
  259.  
  260.     /*
  261.      * Remove the backup unless they want it left around
  262.      */
  263.     if (!P(P_BK))
  264.         remove(backup);
  265.  
  266.     free(backup);
  267.  
  268.     return TRUE;
  269. }
  270.